//
//  ListeningNode.cpp
//  Simulation
//
//  Created by Christopher Kemsley on 3/3/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#include "EveryModel.hpp"

#include "EventMonitor.hpp"
#include "ModuleFactory.hpp"
#include "Transceiver.hpp"

#include "SimulationParameters.hpp"

#include "BroadcastData.hpp"
#include "Log.hpp"

using namespace Sim ;



struct	ListeningModel_CSMA_CASettings : public EveryModelSettings
{
	
	
	
	ListeningModel_CSMA_CASettings	( std::string const & name )
	:	EveryModelSettings(name)
		{
		
		}
} ;

Timer	*	ackTimer;


struct	ListeningModel_CSMA_CA : public EveryModel<ListeningModel_CSMA_CASettings> , public ::ReceiverDelegate , public ::TransmitterDelegate
{
	ListeningModel_CSMA_CA	( ModelVariant const & identity )
	:	EveryModel<ListeningModel_CSMA_CASettings>	( identity )
	,	mProfile		( mConfig.location , mConfig.txRange )
	,	mReceiver		( mConfig.identifier[0] , mProfile , *this )
	,	mTransmitter	( mConfig.identifier[0] , *this )
		{
		}
	
	virtual ~ListeningModel_CSMA_CA ()
		{

		}
	
	
	
	virtual void	mediumDidBecomeIdle ()
		{
			
		}
	virtual void	receiveDidComplete	( Message * message )
		{
		BroadcastInfo::Type		messageType ;
		DeviceID				sender ;
		DeviceID				target ;
		
		decodeBroadcast ( message->bytes , messageType , sender , target ) ;
		
		if ( target == mConfig.identifier[0] )
			{
			Log::notice("ListeningModel_CSMA_CA") << "Got valid message!" ;
			Invocation * i = ObjectContextInvocation<ListeningModel_CSMA_CA,DeviceID>::invocation ( this , &ListeningModel_CSMA_CA::sendACK , sender ) ;
			ackTimer << new Timer ( SimulationParameters::shared().SIFSDuration , i ) ;
			}
		}
	
	TransmitterProfile	mProfile ;
	Receiver			mReceiver ;
	Transmitter			mTransmitter ;
	DP<Timer>			ackTimer ;
	
	
	void	sendACK ( DeviceID const & sender )
	{
		Log::states("ListeningModel_CSMA_CA") << mConfig.identifier << ": Sending ACK" ;
		mReceiver.disable() ;
		Length	length	=	SimulationParameters::shared().controlPacketSize ;
		Byte	buffer		[length] ;
		
		encodeACK ( buffer , length , mConfig.identifier[0] , sender ) ;
		
		mTransmitter . transmit ( buffer,length , sender , mProfile ) ;
	}
	
	virtual void	transmissionDidComplete ()
		{
			Log::states("ListeningModel_CSMA_CA") << mConfig.identifier << ": DONE transmitting" ;
			
			mReceiver.enable() ;
		}
	
	
	
} ;




TypedModuleMaker<ListeningModel_CSMA_CA> _ListeningModel_CSMA_CA ( "csma_ca.passive" ) ;
